/**
 * 类名：HttpUtil
 * @author hmb
 * 创建日期： 2014-8-31 上午10:16:08
 *
 * 备注：封装了HttpClient类的相关操作，可以用于客户端发送Http请求，
 * 也可以用于开发测试单元
 * 
 */
package com.erms.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.erms.util.http.HttpRequest;
import com.erms.util.http.HttpResult;

/**
 * @author hmb
 * 
 */
public class HttpUtil {
	public HttpUtil() {

	}

	/**
	 * HttpClient 的 ssl连接 （暂时没做过测试，不要使用）
	 */
	public static void ssl(String url) {

		CloseableHttpClient httpclient = null;
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore
					.getDefaultType());
			FileInputStream instream = new FileInputStream(new File(
					"d:\\tomcat.keystore"));
			try {
				// 加载keyStore d:\\tomcat.keystore
				trustStore.load(instream, "123456".toCharArray());
			} catch (CertificateException e) {
				e.printStackTrace();
			} finally {
				try {
					instream.close();
				} catch (Exception ignore) {
				}
			}
			// 相信自己的CA和所有自签名的证书
			SSLContext sslcontext = SSLContexts
					.custom()
					.loadTrustMaterial(trustStore,
							new TrustSelfSignedStrategy()).build();
			// 只允许使用TLSv1协议
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslcontext,
					new String[]{"TLSv1"},
					null,
					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
					.build();
			// 创建http请求(get方式)
			HttpGet httpget = new HttpGet(url);

			System.out.println("executing request" + httpget.getRequestLine());
			CloseableHttpResponse response = httpclient.execute(httpget);
			try {
				HttpEntity entity = response.getEntity();
				LogUtil.debug("----------------------------------------");
				LogUtil.debug(response.getStatusLine().toString());
				if (entity != null) {
					LogUtil.debug("Response content length: "
							+ entity.getContentLength());
					LogUtil.debug(EntityUtils.toString(entity));
					EntityUtils.consume(entity);
				}
			} finally {
				response.close();
			}
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} finally {
			if (httpclient != null) {
				try {
					httpclient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}// end ssl

	/**
	 * post方式请求
	 * 
	 * @param url
	 *            请求地址
	 * @param request 请求对象
	 * @param charset
	 *            编码
	 * @return 响应对象
	 */
	public static HttpResult post(String url, HttpRequest request,
			String charset) {

		// 创建默认的httpClient实例.
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		HttpResult result = null;
		// 创建httpPost
		HttpPost httpPost = new HttpPost(url);
		// 创建请求头
		Map<String, String> header = request.getHeaders();
		if (header != null) {
			Set<String> headerKeySet = header.keySet();
			for (Iterator<String> iterator = headerKeySet.iterator(); iterator
					.hasNext();) {
				String headerKey = (String) iterator.next();
				httpPost.setHeader(headerKey, header.get(headerKey));
			}
		}

		UrlEncodedFormEntity uefEntity = null;
		try {
			// 创建参数队列
			uefEntity = new UrlEncodedFormEntity(request.getParams(), charset);
			httpPost.setEntity(uefEntity);
			LogUtil.debug(HttpUtil.class, "执行请求 " + httpPost.getURI());
			response = httpClient.execute(httpPost);
			// 提取结果
			result = new HttpResult(response);

			LogUtil.debug("--------------------------------------");
			// 打印响应状态
			LogUtil.debug(result.getStatusLine().toString());
			LogUtil.debug("Response Location: " + result.getLocation());
			LogUtil.debug("Response Cookie: " + result.getCookie());
			//LogUtil.debug("Response content: \n" + result.getContent());
			LogUtil.debug("--------------------------------------");

		} catch (ClientProtocolException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} catch (UnsupportedEncodingException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} catch (IOException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} finally {
			// 关闭连接,释放资源
			try {
				if (response != null) response.close();
				httpPost.abort();
				httpClient.close();
			} catch (IOException e) {
				LogUtil.error(HttpUtil.class, "", e);
			}
		}
		return result;
	}// end post

	/**
	 * post方式请求，默认编码为'UTF-8'
	 * 
	 * @param url
	 *            请求地址
	 * @param request 请求对象
	 * @return 响应对象
	 */
	public static HttpResult post(String url, HttpRequest request) {

		return post(url, request, "UTF-8");
	}

	/**
	 * get方式请求
	 * 
	 * @param url
	 *            请求地址
	 * @param header
	 *            请求头信息，不需要则传入null
	 * @param charset
	 *            编码
	 * @return 响应对象
	 */
	public static HttpResult get(String url, HttpRequest request, String charset) {

		HttpResult result = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		
		List<NameValuePair> params = request.getParams();
		if (params != null && params.size() > 0) {
			String formatParams = URLEncodedUtils.format(params, charset);
			url = url.contains("?")
					? (url + formatParams)
					: (url + "?" + formatParams);
		}
		HttpGet httpGet = new HttpGet(url);
		try {

			LogUtil.debug("执行请求：" + httpGet.getURI());
			// 创建请求头
			Map<String, String> header = request.getHeaders();
			if (header != null) {
				Set<String> headerKeySet = header.keySet();
				for (Iterator<String> iterator = headerKeySet.iterator(); iterator
						.hasNext();) {
					String headerKey = (String) iterator.next();
					httpGet.setHeader(headerKey, header.get(headerKey));
				}
			}
		
			// 执行get请求
			response = httpClient.execute(httpGet);

			// 提取结果
			result = new HttpResult(response);

			LogUtil.debug("--------------------------------------");
			// 打印响应状态
			LogUtil.debug(result.getStatusLine().toString());
			LogUtil.debug("Response Location: " + result.getLocation());
			LogUtil.debug("Response Cookie: " + result.getCookie());
			//LogUtil.debug("Response content: \n" + result.getContent());
			LogUtil.debug("--------------------------------------");
		} catch (ClientProtocolException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} catch (ParseException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} catch (IOException e) {
			LogUtil.error(HttpUtil.class, "", e);
		} finally {
			// 关闭连接,释放资源
			try {
				if (response != null) response.close();
				httpGet.abort();
				httpClient.close();
			} catch (IOException e) {
				LogUtil.error(HttpUtil.class, "", e);
			}
		}

		return result;
	}// end get

	/**
	 * get 请求，默认编码'UTF-8'
	 * 
	 * @param request 请求对象
	 * @return 响应对象
	 */
	public static HttpResult get(String url, HttpRequest request) {

		return get(url, request, "UTF-8");
	}

	/**
	 * 上传文件（没做过测试，不要使用）
	 * 
	 * @param url
	 *            服务器地址
	 * @param filePath
	 *            文件路径
	 * @param comment
	 *            文件说明
	 * @return 响应对象
	 */
	public static CloseableHttpResponse upload(String url, String filePath,
			String comment) {

		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		try {
			HttpPost httpPost = new HttpPost(url);
			FileBody fileBody = new FileBody(new File(comment));
			StringBody commentBody = new StringBody(comment,
					ContentType.TEXT_PLAIN);

			HttpEntity requestEntity = MultipartEntityBuilder.create()
					.addPart("bin", fileBody).addPart("comment", commentBody)
					.build();
			httpPost.setEntity(requestEntity);

			System.out
					.println("executing request " + httpPost.getRequestLine());
			response = httpClient.execute(httpPost);
			try {
				LogUtil.debug("----------------------------------------");
				LogUtil.debug(response.getStatusLine().toString());
				HttpEntity responseEntity = response.getEntity();
				if (responseEntity != null) {
					LogUtil.debug("Response content length: "
							+ responseEntity.getContentLength());
				}
				EntityUtils.consume(responseEntity);
			} finally {
				response.close();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return response;
	}// end upload

	/**
	 * 上传文件,不添加说明文字（没做过测试，不要使用）
	 * 
	 * @param uri
	 *            服务器地址
	 * @param filePath
	 *            文件路径
	 * @return 响应对象
	 */
	public static CloseableHttpResponse upload(String uri, String filePath) {

		return upload(uri, filePath, "null");
	}
}
